<template>
  <div class="page-container">
    <div
      class="content-wrapper"
      :class="{ 'sidebar-open': sidebarVisible && !isTableMode && windowWidth > 768 }"
      :style="transitionStyle"
    >
      <!-- 面包屑 -->
      <el-breadcrumb separator="/" class="breadcrumb">
        <el-breadcrumb-item :to="{ path: '/projects' }">项目管理</el-breadcrumb-item>
        <el-breadcrumb-item>任务管理</el-breadcrumb-item>
      </el-breadcrumb>

      <!-- 标题和控制按钮 -->
      <div class="header">
        <h2>任务管理 - {{ projectName ? projectName : '未知项目' }}</h2>
        <div class="right-controls">
          <!-- *** 修改点：状态筛选改为下拉框 *** -->
          <el-select
            v-model="currentStatus"
            placeholder="筛选状态"
            clearable
            @change="handleStatusFilterChange"
            class="status-filter-select"
            style="width: 180px; margin-right: 10px"
            size="default"
          >
            <el-option
              v-for="item in statusOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
          <el-button @click="toggleViewMode" class="mode-toggle">
            {{ isTableMode ? '切换到卡片模式' : '切换到表格模式' }}
          </el-button>
          <el-button type="primary" @click="handleAddTask">新增任务</el-button>
        </div>
      </div>

      <!-- 筛选区域 -->
      <div class="filter-section">
        <!-- 移除 :inline="true"，让 flexbox 控制换行 -->
        <el-form class="filter-form">
          <el-form-item label="任务名称" class="filter-item">
            <el-input
              v-model="searchName"
              placeholder="输入任务名称"
              clearable
              @input="debouncedFetchTasks"
              style="width: 200px"
            />
          </el-form-item>
          <el-form-item label="时间范围" class="filter-item">
            <el-date-picker
              v-model="taskDateRange"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              style="width: 240px"
              @change="fetchTasks"
            />
          </el-form-item>
          <!-- 将按钮放在独立的 form-item 中，以便通过 CSS 控制位置 -->
          <el-form-item class="filter-item filter-buttons">
            <el-button type="primary" @click="fetchTasks">查询</el-button>
            <el-button @click="resetTaskFilters">重置</el-button>
          </el-form-item>
        </el-form>
      </div>

      <!-- 卡片模式 -->
      <div v-if="!isTableMode" class="task-cards-wrapper">
        <div class="task-cards">
          <!-- 卡片模板保持不变，但现在由 CSS Grid 布局 -->
          <el-card
            v-for="task in tasks"
            :key="task.id"
            class="task-card animate__animated animate__fadeIn"
            shadow="hover"
            @click="showDetails(task)"
          >
            <div class="card-header">
              <h3 class="task-title" :title="task.name || '未知任务'">
                {{ task.name || '未知任务' }}
              </h3>
              <!-- 将状态标签移到 header 里，更紧凑 -->
              <!-- *** 修改点：更新状态显示 *** -->
              <el-tag
                :type="getStatusType(task.status)"
                size="small"
                class="status-tag card-status-tag"
              >
                {{ getStatusText(task.status) }}
              </el-tag>
            </div>
            <!-- 描述列表保持不变 -->
            <el-descriptions :column="1" size="small" class="card-content" border>
              <el-descriptions-item label="开始时间">{{
                formatTime(task.start_time)
              }}</el-descriptions-item>
              <el-descriptions-item label="截止时间">{{
                formatTime(task.deadline)
              }}</el-descriptions-item>
              <el-descriptions-item label="负责人">
                <span class="ellipsis" :title="task.principal || '-'">{{
                  task.principal || '-'
                }}</span>
              </el-descriptions-item>
              <el-descriptions-item label="更新于">{{
                formatTime(task.last_update_time)
              }}</el-descriptions-item>
            </el-descriptions>
            <!-- 操作按钮保持不变 -->
            <div class="card-actions">
              <el-button type="text" size="small" @click.stop="handleEdit(task)">
                <el-icon><Edit /></el-icon> 编辑
              </el-button>
              <!-- 统一使用 showTaskChanges -->
              <el-button type="text" size="small" @click.stop="showTaskChanges(task)">
                <el-icon><InfoFilled /></el-icon> 变更记录
              </el-button>
              <el-button type="text" size="small" @click.stop="handleAddProblem(task)">
                <el-icon><Plus /></el-icon> 提交进度
              </el-button>
            </div>
            <div class="card-footer">
              <el-popconfirm
                title="确定删除此任务吗？"
                confirm-button-text="确定"
                cancel-button-text="取消"
                @confirm="handleDelete(task)"
                popper-class="delete-popover"
              >
                <template #reference>
                  <el-button type="text" size="small" class="delete-btn" @click.stop>
                    <el-icon><Delete /></el-icon> 删除
                  </el-button>
                </template>
              </el-popconfirm>
            </div>
          </el-card>
          <el-empty
            v-if="!tasks.length"
            description="暂无任务数据显示"
            class="empty-state"
          ></el-empty>
        </div>
        <!-- 分页 -->
        <el-pagination
          v-if="total > 0"
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :total="total || 0"
          layout="total, sizes, prev, pager, next"
          :page-sizes="[5, 10, 20, 50]"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          class="pagination"
        />
      </div>

      <!-- 表格模式 -->
      <div v-if="isTableMode" class="task-table-wrapper">
        <el-table
          :data="tasks"
          border
          stripe
          highlight-current-row
          style="
            width: 100%;
            border-radius: 12px;
            box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
            overflow: hidden;
          "
          ref="taskTable"
          class="pretty-table"
        >
          <el-table-column prop="name" label="任务名称" width="180">
            <template #default="scope">
              <span class="ellipsis" :title="scope.row.name || '未知任务'">{{
                scope.row.name || '未知任务'
              }}</span>
            </template>
          </el-table-column>
          <el-table-column label="开始时间" width="150">
            <template #default="scope">
              {{ formatTime(scope.row.start_time) }}
            </template>
          </el-table-column>
          <el-table-column label="截止时间" width="150">
            <template #default="scope">
              {{ formatTime(scope.row.deadline) }}
            </template>
          </el-table-column>
          <el-table-column label="负责人" width="300">
            <template #default="scope">
              <span class="ellipsis" :title="scope.row.principal || '-'">{{
                scope.row.principal || '-'
              }}</span>
            </template>
          </el-table-column>
          <el-table-column label="状态" width="120" align="center">
            <template #default="scope">
              <el-tag :type="getStatusType(scope.row.status)" size="small">
                {{ getStatusText(scope.row.status) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" align="center" min-width="320" class-name="action-col">
            <template #default="scope">
              <el-button type="primary" size="small" @click="handleAddProblem(scope.row)"
                >提交进度</el-button
              >
              <el-button type="success" size="small" @click="handleEdit(scope.row)" plain
                >编辑</el-button
              >
              <el-button type="info" size="small" @click="showTaskChanges(scope.row)" plain
                >变更记录</el-button
              >
              <el-button type="warning" size="small" @click="showDetails(scope.row)" plain
                >详情</el-button
              >
              <el-popconfirm
                title="确定删除此项目吗？"
                confirm-button-text="确定"
                cancel-button-text="取消"
                @confirm="handleDelete(scope.row)"
                popper-class="delete-popover"
              >
                <template #reference>
                  <el-button type="danger" size="small" plain>
                    <el-icon><Delete /></el-icon> 删除
                  </el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-empty
          v-if="!tasks.length"
          description="暂无任务数据显示"
          class="empty-state pretty-empty"
        ></el-empty>
        <!-- 分页 -->
        <el-pagination
          v-if="total > 0"
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :total="total || 0"
          layout="total, sizes, prev, pager, next"
          :page-sizes="[5, 10, 20, 50]"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          class="pagination"
        />
      </div>

      <!-- 侧边栏 (卡片模式变更记录) -->
      <!-- 条件渲染: 仅在非表格模式且 sidebarVisible 为 true 时显示 -->
      <div class="sidebar" :class="{ visible: sidebarVisible && !isTableMode }">
        <!-- 侧边栏内部结构保持不变 -->
        <div class="sidebar-header">
          <h3>任务变更记录 - {{ currentTaskName || '未选择任务' }}</h3>
          <el-button text circle class="close-btn" @click="sidebarVisible = false">
            <el-icon size="16"><Close /></el-icon>
          </el-button>
        </div>
        <div class="sidebar-content">
          <el-form class="filter-form sidebar-filter-form">
            <el-form-item label="时间范围" class="full-width">
              <el-date-picker
                v-model="taskChangesDateRange"
                type="daterange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                size="small"
                style="width: 100%"
                @change="fetchTaskChangesSidebar"
              />
            </el-form-item>
            <el-form-item class="button-group sidebar-button-group">
              <div style="display: flex; justify-content: flex-end; gap: 10px; width: 100%">
                <el-button type="primary" size="small" @click="fetchTaskChangesSidebar"
                  >查询</el-button
                >
                <el-button size="small" @click="resetTaskChangesFilters" plain>重置</el-button>
              </div>
            </el-form-item>
          </el-form>
          <div class="changes-list" v-if="currentTaskId">
            <ul class="timeline">
              <li
                v-for="(changeGroup, index) in groupedTaskChanges"
                :key="index"
                class="timeline-item"
              >
                <div class="timeline-content">
                  <p class="change-description">
                    <el-icon><Clock /></el-icon>
                    <span>
                      {{ changeGroup.operator }} 在
                      {{ formatTimeFull(changeGroup.change_time) }} 进行了以下变更：
                      <ul class="change-details">
                        <li v-for="(change, idx) in changeGroup.changes" :key="idx">
                          {{ change.summary }}
                        </li>
                      </ul>
                    </span>
                  </p>
                </div>
              </li>
            </ul>
          </div>
          <div v-else class="no-selection">
            <p>请选择一个任务以查看变更记录</p>
          </div>
        </div>
      </div>

      <!-- 变更记录弹窗 (表格模式) -->
      <!-- 条件渲染: 仅在表格模式且 changesDialogVisible 为 true 时显示 -->
      <el-dialog
        :title="'任务变更记录 - ' + currentTaskName"
        v-model="changesDialogVisible"
        :width="dialogWidth"
        class="change-log-dialog"
        @close="resetChangesDialog"
        top="5vh"
      >
        <!-- *** 修改点：弹窗内的表单布局 *** -->
        <el-form class="dialog-filter-form">
          <el-form-item label="时间范围" class="full-width">
            <el-date-picker
              v-model="taskChangesDateRange"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              style="width: 100%"
              @change="fetchChangesDialog"
            />
          </el-form-item>
          <!-- 将按钮放在独立的 form-item 中，位于日期选择器下方 -->
          <el-form-item class="dialog-button-group">
            <!-- 使用 div 并设置 flex 布局，让按钮在同一行且靠右 -->
            <div style="display: flex; justify-content: flex-end; gap: 10px; width: 100%">
              <el-button type="primary" @click="fetchChangesDialog">查询</el-button>
              <el-button @click="resetTaskChangesFilters" plain>重置</el-button>
            </div>
          </el-form-item>
        </el-form>
        <!-- 时间线显示保持不变 -->
        <div class="changes-list dialog-changes-list" v-if="dialogGroupedChanges.length">
          <ul class="timeline">
            <li
              v-for="(changeGroup, index) in dialogGroupedChanges"
              :key="index"
              class="timeline-item"
            >
              <div class="timeline-content">
                <p class="change-description">
                  <el-icon><Clock /></el-icon>
                  <span>
                    {{ changeGroup.operator }} 在
                    {{ formatTimeFull(changeGroup.change_time) }} 进行了以下变更：
                    <ul class="change-details">
                      <li v-for="(change, idx) in changeGroup.changes" :key="idx">
                        {{ change.summary }}
                      </li>
                    </ul>
                  </span>
                </p>
              </div>
            </li>
          </ul>
        </div>
        <div v-else class="no-selection">
          <p>暂无变更记录</p>
        </div>
      </el-dialog>

      <!-- 查看详情对话框 -->
      <el-dialog
        title="任务详情"
        v-model="detailsDialogVisible"
        :width="dialogWidth"
        class="details-dialog"
        @close="resetDetailsDialog"
        top="5vh"
      >
        <!-- 详情内容保持不变 -->
        <div class="details-content">
          <div class="detail-item">
            <span class="label">任务名称：</span>
            <span class="value">{{ currentTaskDetails.name || '未知任务' }}</span>
          </div>
          <div class="detail-item">
            <span class="label">开始时间：</span>
            <span class="value">{{ formatTime(currentTaskDetails.start_time) }}</span>
          </div>
          <div class="detail-item">
            <span class="label">截止时间：</span>
            <span class="value">{{ formatTime(currentTaskDetails.deadline) }}</span>
          </div>
          <div class="detail-item">
            <span class="label">负责人：</span>
            <span class="value">{{ currentTaskDetails.principal || '-' }}</span>
          </div>
          <div class="detail-item">
            <span class="label">状态：</span>
            <el-tag :type="getStatusType(currentTaskDetails.status)" size="small">{{
              getStatusText(currentTaskDetails.status)
            }}</el-tag>
          </div>
          <div class="detail-item">
            <span class="label">最后更新：</span>
            <span class="value">{{ formatTime(currentTaskDetails.last_update_time) }}</span>
          </div>
          <div class="detail-item long-text">
            <span class="label">描述：</span>
            <div class="value scrollable subtasks-list">
              <div v-for="(subtask, index) in parsedSubtasks" :key="index" class="subtask-item">
                <div class="subtask-content">
                  <el-checkbox :modelValue="subtask.completed" disabled></el-checkbox>
                  <span :class="{ 'completed-subtask': subtask.completed }">{{
                    subtask.text
                  }}</span>
                </div>
              </div>
              <div v-if="!parsedSubtasks.length">{{ currentTaskDetails.description || '-' }}</div>
            </div>
          </div>
          <div class="detail-item long-text">
            <span class="label">进度：</span>
            <div class="value scrollable">{{ currentTaskDetails.problem || '-' }}</div>
          </div>
          <div class="detail-item long-text">
            <span class="label">备注：</span>
            <div class="value scrollable">{{ currentTaskDetails.remark || '-' }}</div>
          </div>
        </div>
      </el-dialog>

      <!-- 编辑/新增任务对话框 -->
      <el-dialog
        :title="editForm.id ? '编辑任务' : '新增任务'"
        v-model="editDialogVisible"
        :width="dialogWidth"
        class="edit-dialog"
        @close="resetEditForm"
        top="5vh"
        :close-on-click-modal="false"
      >
        <!-- 编辑表单保持不变 -->
        <el-form
          :model="editForm"
          :rules="editRules"
          ref="editFormRef"
          label-width="100px"
          class="edit-form"
          @submit.prevent="submitEdit"
        >
          <el-form-item label="任务名称" prop="name">
            <el-input v-model="editForm.name"></el-input>
          </el-form-item>
          <el-form-item
            v-for="(desc, index) in editForm.descriptions"
            :key="index"
            :label="index === 0 ? '任务描述' : ''"
            :prop="'descriptions.' + index"
            class="description-item"
          >
            <!-- :rules="editRules['descriptions.0']"  -->
            <div class="subtask-container">
              <el-checkbox
                v-model="editForm.completedSubtasks[index]"
                class="subtask-checkbox"
                @change="handleSubtaskCompletion(index)"
              ></el-checkbox>
              <el-input
                v-model="editForm.descriptions[index]"
                type="textarea"
                :rows="2"
                placeholder="请输入描述信息"
                style="width: calc(100% - 40px)"
              ></el-input>
              <el-button
                v-if="editForm.descriptions.length > 1"
                @click="removeDescriptionField(index)"
                type="danger"
                size="small"
                title="移除此项描述"
                ><Delete
              /></el-button>
            </div>
          </el-form-item>
          <el-form-item>
            <el-button @click="addDescriptionField" :icon="Plus" type="primary" link>
              增加描述项
            </el-button>
          </el-form-item>
          <!-- <el-form-item label="遇到的问题" prop="problem">
            <el-input v-model="editForm.problem" type="textarea" :rows="2"></el-input>
          </el-form-item> -->
          <el-form-item label="备注" prop="remark">
            <el-input v-model="editForm.remark" type="textarea" :rows="2"></el-input>
          </el-form-item>
          <el-form-item label="开始时间" prop="start_time">
            <el-date-picker
              v-model="editForm.start_time"
              type="date"
              placeholder="选择开始日期"
              style="width: 100%"
              value-format="x"
            />
          </el-form-item>
          <el-form-item label="截止时间" prop="deadline">
            <el-date-picker
              v-model="editForm.deadline"
              type="date"
              placeholder="选择截止日期"
              style="width: 100%"
              value-format="x"
            />
          </el-form-item>
          <el-form-item label="负责人" prop="principal">
            <el-input v-model="editForm.principal"></el-input>
          </el-form-item>
          <el-form-item label="状态" prop="status">
            <el-select
              v-model="editForm.status"
              placeholder="请选择状态"
              style="width: 100%"
              @change="handleStatusChangeInEdit"
            >
              <el-option
                v-for="item in statusOptions.filter((opt) => opt.value !== null)"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
        </el-form>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="editDialogVisible = false">取消</el-button>
            <el-button type="primary" @click="submitEdit">确定</el-button>
          </span>
        </template>
      </el-dialog>

      <!-- 新增问题对话框 -->
      <el-dialog
        title="提交进度"
        v-model="addProblemDialogVisible"
        :width="dialogWidth"
        class="problem-dialog"
        @close="resetProblemForm"
        top="5vh"
        :close-on-click-modal="false"
      >
        <!-- 新增问题表单保持不变 -->
        <el-form
          :model="problemForm"
          :rules="problemRules"
          ref="problemFormRef"
          label-width="100px"
          class="edit-form"
          @submit.prevent="submitProblem"
        >
          <el-form-item label="进度描述" prop="new_problem">
            <el-input
              v-model="problemForm.new_problem"
              type="textarea"
              :rows="4"
              placeholder="请输入最新进度"
            ></el-input>
          </el-form-item>
        </el-form>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="addProblemDialogVisible = false">取消</el-button>
            <el-button type="primary" @click="submitProblem">确定</el-button>
          </span>
        </template>
      </el-dialog>
    </div>
  </div>
</template>

<script>
import dayjs from 'dayjs';
// 引入 API 函数
import {
  fetchTasks,
  fetchProjects,
  updateTask,
  fetchTaskChange,
  createTask,
  deleteTask,
  addProblem,
} from '../api/index'; // 确认 addProblem API 已导入
// 引入 Element Plus 图标 和 消息提示/确认框
import { Edit, Close, Clock, InfoFilled, Delete, Plus } from '@element-plus/icons-vue';
import _ from 'lodash';
import { nextTick } from 'vue'; // 引入 Vue 3 hooks
import { ElMessage, ElMessageBox } from 'element-plus'; // 明确导入
import { STATUS_MAP, STATUS_TEXT, STATUS_TYPE } from '@/utils/taskStatus';
import { formatTime, formatTimeFull } from '@/utils/date';

export default {
  components: { Edit, Close, Clock, InfoFilled, Delete, Plus },
  data() {
    const validateDateRange = (rule, value, callback) => {
      const startTime = this.editForm.start_time ? dayjs(this.editForm.start_time) : null;
      const deadline = this.editForm.deadline ? dayjs(this.editForm.deadline) : null; // 使用 this.editForm.deadline

      // 只在两个日期都存在时才比较
      if (startTime && deadline && startTime.isAfter(deadline)) {
        callback(new Error('截止时间不能早于开始时间'));
      } else {
        callback(); // 其他情况（包括只有一个日期或日期正确）都通过此校验
      }
    };

    // *** 新增：截止时间的动态必填校验函数 ***
    const validateDeadlineRequired = (rule, value, callback) => {
      const status = this.editForm.status;
      const deadline = this.editForm.deadline; // 获取当前截止时间的值

      // 检查状态是否属于需要必填截止时间的 (4)
      if ([STATUS_MAP.FINISHED].includes(status)) {
        // 如果是这些状态，且截止时间为空，则校验失败
        if (!deadline) {
          callback(new Error('状态为完成后，截止时间不能为空'));
        } else {
          // 如果状态需要必填且已填写，调用日期范围校验
          validateDateRange(rule, value, callback);
        }
      } else {
        // 如果状态不需要必填 (0, 1, 2, 3)
        // 检查是否填写了截止时间，如果填写了，仍需进行日期范围校验
        if (deadline) {
          validateDateRange(rule, value, callback);
        } else {
          // 如果未填写，直接通过校验
          callback();
        }
      }
    };

    return {
      searchName: '',
      projectName: '',
      tasks: [],
      total: 0,
      currentPage: 1,
      pageSize: 10,
      taskDateRange: [], // 任务列表日期筛选
      editDialogVisible: false,
      editForm: {
        id: '',
        guid: '',
        name: '',
        // *** 修改点：task_desc 改为 descriptions 数组 ***
        descriptions: [''], // 初始化为一个空字符串数组
        completedSubtasks: [false], // 记录每个小任务的完成状态
        problem: '',
        remark: '',
        start_time: null,
        deadline: null,
        principal: '',
        status: STATUS_MAP.PENDING, // 默认状态
      },
      editRules: {
        name: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
        start_time: [
          { required: true, message: '请选择开始时间', trigger: 'change' },
          { validator: validateDateRange, trigger: 'change' }, // 开始时间仍需校验范围
        ],
        // *** 修改点：应用新的截止时间校验规则 ***
        deadline: [{ validator: validateDeadlineRequired, trigger: 'change' }],
        status: [{ required: true, message: '请选择状态', trigger: 'change' }],
        principal: [{ required: true, message: '请输入负责人', trigger: 'blur' }],
        // descriptions 校验（如果需要，例如第一项必填）
        //  'descriptions.0': [ // 对数组第一项添加校验
        //      { required: true, message: '请至少输入第一项描述', trigger: 'blur' }
        //  ]
      },
      sidebarVisible: false, // 卡片模式变更记录侧边栏
      taskChanges: [],
      taskChangesTotal: 0,
      taskChangesDateRange: [], // 变更记录日期筛选
      currentTaskId: null,
      currentTaskName: '',
      currentStatus: null, // 任务列表状态筛选，null 表示全部
      isTableMode: false,
      changesDialogVisible: false, // 表格模式变更记录弹窗
      dialogChanges: [],
      disableTransition: false,
      detailsDialogVisible: false, // 任务详情弹窗
      currentTaskDetails: {},
      addProblemDialogVisible: false, // 新增问题弹窗
      problemForm: {
        task_id: '',
        new_problem: '',
      },
      problemRules: {
        new_problem: [{ required: true, message: '请输入问题描述', trigger: 'blur' }],
      },
      windowWidth: window.innerWidth,
      // *** 新增：状态筛选下拉框选项 (与 Projects.vue 相同) ***
      statusOptions: [
        { label: '全部状态', value: null },
        ...Object.entries(STATUS_TEXT).map(([value, label]) => ({
          label,
          value: Number(value),
        })),
      ],
    };
  },
  computed: {
    transitionStyle() {
      return this.disableTransition ? { transition: 'none' } : {};
    },
    groupedTaskChanges() {
      return this.groupChanges(this.taskChanges);
    },
    dialogGroupedChanges() {
      return this.groupChanges(this.dialogChanges); // 对弹窗数据使用相同的分组逻辑
    },
    // 计算属性用于响应式弹窗宽度
    dialogWidth() {
      if (this.windowWidth > 1200) {
        return '50%';
      } else if (this.windowWidth > 768) {
        return '70%';
      } else {
        return '90%'; // 小屏幕使用更宽的百分比
      }
    },
    // 解析当前任务详情中的小任务
    parsedSubtasks() {
      if (!this.currentTaskDetails.description) return [];

      const description = this.currentTaskDetails.description;
      const lines = description.split('\n');

      return lines
        .map((line) => {
          if (!line.trim()) return null; // 忽略空行

          const isCompleted = line.endsWith('complete');
          const text = isCompleted ? line.substring(0, line.length - 'complete'.length) : line;

          return {
            text,
            completed: isCompleted,
          };
        })
        .filter(Boolean); // 移除空值
    },
  },
  created() {
    this.debouncedFetchTasks = _.debounce(this.fetchTasks, 500);
    // *** 新增：添加窗口大小变化监听器 ***
    window.addEventListener('resize', this.handleResize);
  },
  beforeUnmount() {
    // Vue 3 使用 beforeUnmount
    // *** 新增：移除监听器 ***
    window.removeEventListener('resize', this.handleResize);
  },
  mounted() {
    this.fetchProjectName();
    this.fetchTasks();
    this.handleResize(); // 初始化窗口宽度
    if (this.$route.query.autoAddTask === 'true') {
      console.log('检测到 autoAddTask 查询参数，准备打开新增任务弹窗');
      // 使用 nextTick 确保 DOM 更新完毕后再打开弹窗
      nextTick(() => {
        this.handleAddTask(); // 调用打开新增任务弹窗的方法
      });
      // 可选：移除查询参数，避免刷新页面时再次触发
      this.$router.replace({ query: { ...this.$route.query, autoAddTask: undefined } });
    }
  },
  methods: {
    // *** 新增：处理窗口大小变化的方法 ***
    handleResize() {
      this.windowWidth = window.innerWidth;
    },

    // --- 数据获取 ---
    async fetchTasks() {
      console.log('获取任务参数:', {
        task_name: this.searchName,
        project_id: this.$route.params.projectId,
        start_time:
          this.taskDateRange && this.taskDateRange[0]
            ? dayjs(this.taskDateRange[0]).unix()
            : undefined,
        deadline:
          this.taskDateRange && this.taskDateRange[1]
            ? dayjs(this.taskDateRange[1]).endOf('day').unix()
            : undefined, // 包含结束日期当天
        page_num: this.currentPage,
        page_size: this.pageSize,
        status: this.currentStatus,
      });
      try {
        const params = {
          task_name: this.searchName || undefined, // 空字符串转为 undefined
          project_id: this.$route.params.projectId,
          start_time:
            this.taskDateRange && this.taskDateRange[0]
              ? dayjs(this.taskDateRange[0]).startOf('day').unix()
              : undefined,
          deadline:
            this.taskDateRange && this.taskDateRange[1]
              ? dayjs(this.taskDateRange[1]).endOf('day').unix()
              : undefined,
          page_num: this.currentPage,
          page_size: this.pageSize,
          // 仅当 currentStatus 不是 null 时才包含 status 参数 (0 是有效状态)
          ...(this.currentStatus !== null && { status: this.currentStatus }),
        };
        // 移除值为 undefined 的键
        Object.keys(params).forEach((key) => params[key] === undefined && delete params[key]);

        const response = await fetchTasks(params);
        // 假设拦截器已处理 response.data
        if (response.data.status === 200) {
          this.tasks = response.data.result.items || [];
          this.total = Number(response.data.result.total) || 0; // 确保 total 是数字
          console.log('任务获取成功:', this.tasks, '总数:', this.total);
        } else {
          console.error('获取任务列表失败 (API):', response);
          ElMessage.error('获取任务列表失败: ' + (response?.data.message || '未知错误'));
          this.tasks = []; // 失败时清空列表
          this.total = 0;
        }
      } catch (error) {
        console.error('获取任务失败 (Catch):', error);
        ElMessage.error('获取任务时发生网络错误或未知异常');
        this.tasks = []; // 严重错误时清空列表
        this.total = 0;
      }
    },
    async fetchProjectName() {
      try {
        const projectId = this.$route.params.projectId;
        if (!projectId) {
          console.error('路由参数中缺少项目ID');
          ElMessage.error('无法获取项目ID');
          this.projectName = '未知项目';
          return;
        }
        // 假设 fetchProjects 需要对象参数，即使是单个 ID 查询
        const response = await fetchProjects({ id: Number(projectId) }); // 确保 ID 是数字（如果需要）
        if (response.data.status === 200) {
          this.projectName = response.data.result.data_list[0].name;
        } else {
          console.warn('获取项目名称失败或未找到项目:', response);
          this.projectName = '未知项目'; // 设置默认名称
        }
      } catch (error) {
        console.error('获取项目名称失败 (Catch):', error);
        ElMessage.error('无法获取项目名称');
        this.projectName = '未知项目';
      }
    },

    // --- 格式化与辅助函数 ---
    formatTime,
    formatTimeFull,
    // *** 修改点：更新状态文本和类型获取 ***
    getStatusText(status) {
      return STATUS_TEXT[status] !== undefined ? STATUS_TEXT[status] : '未知状态';
    },
    getStatusType(status) {
      return STATUS_TYPE[status] || 'info';
    },

    handleEdit(task) {
      // 打开编辑
      // 解析任务描述，提取小任务和完成状态
      const { subtasks, completedStatus } = this.parseTaskDescription(task.description || '');

      this.editForm = {
        id: task.id,
        guid: task.guid,
        name: task.name || '',
        descriptions: subtasks.length > 0 ? subtasks : [''],
        completedSubtasks: completedStatus,
        problem: task.problem || '',
        remark: task.remark || '',
        start_time: task.start_time ? task.start_time : null,
        deadline: task.deadline ? task.deadline : null,
        principal: task.principal || '',
        status: task.status !== undefined ? task.status : STATUS_MAP.PENDING,
      };

      // 确保 descriptions 至少有一项
      if (this.editForm.descriptions.length === 0) {
        this.editForm.descriptions.push('');
        this.editForm.completedSubtasks.push(false);
      }

      this.editDialogVisible = true;
      nextTick(() => {
        // 打开弹窗后清除校验
        if (this.$refs.editFormRef) {
          this.$refs.editFormRef.clearValidate();
        }
      });
    },
    handleAddTask() {
      // 打开新增
      this.resetEditForm();
      this.editForm.status = STATUS_MAP.PENDING;
      this.editDialogVisible = true;
      nextTick(() => {
        if (this.$refs.editFormRef) {
          this.$refs.editFormRef.clearValidate();
        }
      });
    },
    async handleDelete(task) {
      // 使用 ElMessageBox 进行二次确认
      ElMessageBox.confirm(
        `确定要删除任务 "${task.name || '该任务'}" 吗？此操作无法撤销。`, // 提示信息
        '确认删除', // 标题
        {
          confirmButtonText: '确定删除',
          cancelButtonText: '取消',
          type: 'warning', // 警告类型图标
          customClass: 'delete-message-box', // 添加自定义类名以便样式化
        },
      )
        .then(async () => {
          // 用户点击了“确定删除”
          try {
            // 假设删除 API 需要 task.guid
            const params = { guid: task.guid };
            if (!params.guid) {
              ElMessage.error('无法删除：任务缺少唯一标识符 (guid)');
              return; // 阻止执行删除
            }
            console.log('尝试删除任务，参数:', params);
            const response = await deleteTask(params);
            if (response.data.status === 200) {
              ElMessage.success(response.data.message || '任务删除成功');
              // 刷新任务列表，或者为了更好的体验可以先在本地移除该项
              this.fetchTasks();
            } else {
              ElMessage.error('删除任务失败: ' + (response?.data.message || '未知错误'));
            }
          } catch (error) {
            console.error('删除任务失败 (Catch):', error);
            ElMessage.error('删除任务时发生网络错误或未知异常');
          }
        })
        .catch(() => {
          // 用户点击了“取消”或关闭了弹窗
          ElMessage.info('删除操作已取消');
        });
    },
    resetEditForm() {
      // 重置表单
      if (this.$refs.editFormRef) {
        this.$refs.editFormRef.resetFields();
        this.$refs.editFormRef.clearValidate();
      }
      this.editForm = {
        id: '',
        guid: '',
        name: '',
        descriptions: [''],
        completedSubtasks: [false],
        problem: '',
        remark: '',
        start_time: null,
        deadline: null,
        principal: '',
        status: STATUS_MAP.PENDING,
      };
    },

    // 添加/移除描述字段的方法
    addDescriptionField() {
      this.editForm.descriptions.push('');
      this.editForm.completedSubtasks.push(false);
    },
    removeDescriptionField(index) {
      if (this.editForm.descriptions.length > 1) {
        this.editForm.descriptions.splice(index, 1);
        this.editForm.completedSubtasks.splice(index, 1);
      } else {
        ElMessage.warning('至少需要保留一项描述');
      }
    },

    // 处理小任务完成状态变化
    handleSubtaskCompletion(index) {
      // 可以在这里添加额外的逻辑，如果需要的话
      console.log(`小任务 ${index} 完成状态变更为: ${this.editForm.completedSubtasks[index]}`);
    },

    // 解析任务描述字符串，提取小任务和完成状态
    parseTaskDescription(description) {
      if (!description) {
        return { subtasks: [''], completedStatus: [false] };
      }

      // 按换行符分割成小任务
      const lines = description.split('\n');
      const subtasks = [];
      const completedStatus = [];

      lines.forEach((line) => {
        if (line.trim()) {
          // 忽略空行
          const isCompleted = line.endsWith('complete');
          // 如果是已完成的小任务，移除末尾的'complete'标记
          const taskText = isCompleted ? line.substring(0, line.length - 'complete'.length) : line;
          subtasks.push(taskText);
          completedStatus.push(isCompleted);
        }
      });

      // 如果没有有效的小任务，返回一个空的默认项
      if (subtasks.length === 0) {
        subtasks.push('');
        completedStatus.push(false);
      }

      return { subtasks, completedStatus };
    },
    async submitEdit() {
      // 提交编辑/新增
      if (!this.$refs.editFormRef) return;
      this.$refs.editFormRef.validate(async (valid) => {
        if (valid) {
          // 处理小任务描述和完成状态
          const formattedDescriptions = this.editForm.descriptions
            .map((desc, index) => {
              if (!desc || desc.trim() === '') return null; // 忽略空描述
              // 如果小任务已完成，添加'complete'标记
              return this.editForm.completedSubtasks[index] ? `${desc}complete` : desc;
            })
            .filter(Boolean); // 移除空值

          // 合并为字符串，用换行符分隔
          const descriptionString = formattedDescriptions.join('\n');
          let action;
          try {
            const params = {
              task_name: this.editForm.name,
              // *** 修改点：发送处理后的描述字符串，字段名可能为 task_desc ***
              task_desc: descriptionString, // 请确认后端接口期望的字段名
              problem: this.editForm.problem,
              remark: this.editForm.remark,
              start_time: this.editForm.start_time ? dayjs(this.editForm.start_time).unix() : 0,
              deadline: this.editForm.deadline ? dayjs(this.editForm.deadline).unix() : 0,
              principal: this.editForm.principal,
              status: this.editForm.status,
              project_id: this.$route.params.projectId, // 添加关联的项目 ID
            };

            let response;
            action = '新增';
            if (this.editForm.id) {
              params.id = this.editForm.id;
              params.guid = this.editForm.guid; // 更新可能需要 guid
              action = '更新';
              response = await updateTask(params);
            } else {
              response = await createTask(params);
            }

            if (response.data.status === 200) {
              ElMessage.success(response.data.message || `任务${action}成功`);
              this.editDialogVisible = false;
              this.fetchTasks();
            } else {
              ElMessage.error(`任务${action}失败: ` + (response?.data.message || '未知错误'));
            }
          } catch (error) {
            console.error(`任务${action}失败 (Catch):`, error);
            ElMessage.error(`任务${action}时发生网络错误`);
          }
        } else {
          ElMessage.warning('请检查表单内容是否符合要求');
          return false;
        }
      });
    },

    // *** 修改点：处理状态筛选变化 ***
    handleStatusFilterChange(newStatus) {
      this.currentStatus = newStatus;
      this.currentPage = 1; // 筛选变化时回到第一页
      this.fetchTasks(); // 重新获取任务列表
    },
    // *** 新增：处理编辑弹窗状态变化，触发截止日期校验 ***
    handleStatusChangeInEdit() {
      if (this.$refs.editFormRef) {
        this.$refs.editFormRef.validateField('deadline');
        // 如果第一项描述的必填性依赖状态，也可以在这里触发
        // this.$refs.editFormRef.validateField('descriptions.0');
      }
    },

    // --- 变更记录相关 ---
    // 统一的显示变更记录入口
    showTaskChanges(task) {
      this.currentTaskId = task.id;
      this.currentTaskName = task.name || '未知任务';
      this.taskChangesDateRange = []; // 打开时重置日期筛选

      if (this.isTableMode) {
        // 表格模式：打开弹窗
        this.dialogChanges = []; // 清空上次弹窗的数据
        this.changesDialogVisible = true;
        this.fetchChangesDialog(); // 获取弹窗数据
      } else {
        // 卡片模式：切换侧边栏
        // 如果侧边栏已为当前任务打开，则关闭；否则打开
        if (this.sidebarVisible && this.currentTaskId === task.id) {
          this.sidebarVisible = false;
        } else {
          this.taskChanges = []; // 清空上次侧边栏数据
          this.sidebarVisible = true;
          this.fetchTaskChangesSidebar(); // 获取侧边栏数据
        }
      }
    },
    async fetchTaskChangesSidebar() {
      if (!this.currentTaskId) return;
      try {
        const params = {
          obj_id: this.currentTaskId,
          start_time:
            this.taskChangesDateRange && this.taskChangesDateRange[0]
              ? dayjs(this.taskChangesDateRange[0]).startOf('day').unix()
              : undefined,
          // 结束时间需要包含当天
          deadline:
            this.taskChangesDateRange && this.taskChangesDateRange[1]
              ? dayjs(this.taskChangesDateRange[1]).endOf('day').unix()
              : undefined,
          // 如果侧边栏需要分页，在此添加 page_num, page_size
        };
        Object.keys(params).forEach((key) => params[key] === undefined && delete params[key]);

        const response = await fetchTaskChange(params);
        if (response.data.status === 200) {
          this.taskChanges = response.data.result.items || [];
          // this.taskChangesTotal = response.result.total || 0; // 如果使用分页
        } else {
          ElMessage.error(
            '获取任务变更记录(侧边栏)失败: ' + (response?.data.message || '未知错误'),
          );
          this.taskChanges = []; // 失败时清空
        }
      } catch (error) {
        console.error('获取任务变更记录(侧边栏)失败 (Catch):', error);
        ElMessage.error('获取任务变更记录(侧边栏)时发生网络错误或未知异常');
        this.taskChanges = []; // 严重错误时清空
      }
    },
    async fetchChangesDialog() {
      if (!this.currentTaskId) return;
      try {
        const params = {
          obj_id: this.currentTaskId,
          start_time:
            this.taskChangesDateRange && this.taskChangesDateRange[0]
              ? dayjs(this.taskChangesDateRange[0]).startOf('day').unix()
              : undefined,
          deadline:
            this.taskChangesDateRange && this.taskChangesDateRange[1]
              ? dayjs(this.taskChangesDateRange[1]).endOf('day').unix()
              : undefined,
          // 如果弹窗需要分页，在此添加
        };
        Object.keys(params).forEach((key) => params[key] === undefined && delete params[key]);

        const response = await fetchTaskChange(params);
        if (response.data.status === 200) {
          this.dialogChanges = response.data.result.items || [];
        } else {
          ElMessage.error('获取任务变更记录(弹窗)失败: ' + (response?.data.message || '未知错误'));
          this.dialogChanges = []; // 失败时清空
        }
      } catch (error) {
        console.error('获取任务变更记录(弹窗)失败 (Catch):', error);
        ElMessage.error('获取任务变更记录(弹窗)时发生网络错误或未知异常');
        this.dialogChanges = []; // 严重错误时清空
      }
    },
    resetTaskChangesFilters() {
      this.taskChangesDateRange = [];
      // 根据当前显示的模式重新获取数据
      if (this.changesDialogVisible) {
        // 检查弹窗是否可见
        this.fetchChangesDialog();
      } else if (this.sidebarVisible) {
        // 检查侧边栏是否可见
        this.fetchTaskChangesSidebar();
      }
    },
    resetChangesDialog() {
      this.dialogChanges = [];
      this.taskChangesDateRange = []; // 关闭时也重置筛选器
      // this.currentTaskId = null; // 通常不在这里重置，因为弹窗关闭不代表取消选择
      // this.currentTaskName = '';
      // changesDialogVisible 由 v-model 控制关闭
    },

    // --- 列表筛选与视图切换 ---
    resetTaskFilters() {
      this.searchName = '';
      this.taskDateRange = [];
      this.currentPage = 1; // 回到第一页
      this.currentStatus = null; // 清除状态筛选
      this.fetchTasks();
    },

    toggleViewMode() {
      this.disableTransition = true; // 切换时禁用过渡动画
      this.isTableMode = !this.isTableMode;

      // 切换到表格模式时，关闭侧边栏
      if (this.isTableMode) {
        this.sidebarVisible = false;
      }
      // 切换到卡片模式时，关闭可能打开的变更记录弹窗
      if (!this.isTableMode) {
        this.changesDialogVisible = false;
      }

      // 使用 nextTick 和 setTimeout 确保 DOM 更新后再启用过渡
      // 并可能需要重新计算表格布局（如果表格列是动态的）
      nextTick(() => {
        setTimeout(() => {
          if (this.isTableMode && this.$refs.taskTable) {
            this.$refs.taskTable.doLayout(); // 重新计算表格布局
          }
          this.disableTransition = false; // 重新启用过渡动画
        }, 50); // 短暂延迟
      });
    },

    // --- 分页处理 ---
    handleSizeChange(newSize) {
      this.pageSize = newSize;
      this.currentPage = 1; // 页大小变化时回到第一页
      this.fetchTasks();
    },
    handleCurrentChange(newPage) {
      this.currentPage = newPage;
      this.fetchTasks();
    },

    // --- 分组变更记录 (公用逻辑) ---
    groupChanges(changes) {
      if (!changes || changes.length === 0) return []; // 处理空数组
      const grouped = {};
      changes.forEach((change) => {
        // 使用 操作者 + 时间戳 作为分组依据
        const key = `${change.operator || '未知用户'}-${change.change_time}`;
        if (!grouped[key]) {
          grouped[key] = {
            operator: change.operator || '未知用户',
            change_time: change.change_time,
            changes: [], // 存储该时间点的具体变更项
          };
        }
        // 确保 change 对象中有 summary 字段
        grouped[key].changes.push({ summary: change.summary || '无具体描述' });
      });
      // 将分组后的对象转为数组，并按时间降序排列 (最新在前)
      return Object.values(grouped).sort(
        (a, b) =>
          dayjs(Number(b.change_time) * 1000).unix() - dayjs(Number(a.change_time) * 1000).unix(),
      );
    },

    // --- 任务详情 ---
    showDetails(task) {
      this.currentTaskDetails = { ...task }; // 创建副本以显示
      this.detailsDialogVisible = true;
    },
    resetDetailsDialog() {
      this.currentTaskDetails = {};
      // detailsDialogVisible 由 v-model 控制关闭
    },

    // --- 新增问题 ---
    handleAddProblem(task) {
      this.resetProblemForm(); // 先重置表单
      this.problemForm.task_id = task.id; // 设置关联的任务 ID
      if (!this.problemForm.task_id) {
        ElMessage.error('无法新增问题：任务 ID 缺失');
        return; // 阻止打开弹窗
      }
      this.addProblemDialogVisible = true;
    },
    resetProblemForm() {
      if (this.$refs.problemFormRef) {
        this.$refs.problemFormRef.resetFields(); // 重置表单项的值和校验状态
        this.$refs.problemFormRef.clearValidate(); // 确保清除校验提示
      }
      this.problemForm = {
        task_id: '', // 通常重置时清空 task_id
        new_problem: '',
      };
      // addProblemDialogVisible 由 v-model 控制或在取消/成功后设为 false
    },
    async submitProblem() {
      if (!this.$refs.problemFormRef) return;
      this.$refs.problemFormRef.validate(async (valid) => {
        if (valid) {
          if (!this.problemForm.task_id) {
            ElMessage.error('提交失败：缺少任务 ID');
            return; // 防止提交
          }
          try {
            const params = {
              task_id: this.problemForm.task_id,
              new_problem: this.problemForm.new_problem,
            };
            // 假设你的 API 文件中有 addProblem 函数
            const response = await addProblem(params);
            if (response.data.status === 200) {
              ElMessage.success(response.data.message || '进度添加成功');
              this.addProblemDialogVisible = false;
              // 选项 1: 刷新整个列表 (简单)
              this.fetchTasks();
              // 选项 2: 本地更新任务数据 (如果列表很长，体验更好，但更复杂)
              // const taskIndex = this.tasks.findIndex(t => t.id === params.task_id);
              // if (taskIndex > -1) {
              //   // 需要根据 problem 字段如何存储来决定如何追加
              //   this.tasks[taskIndex].problem = (this.tasks[taskIndex].problem ? this.tasks[taskIndex].problem + '\n' : '') + params.new_problem;
              // }
            } else {
              ElMessage.error('添加问题失败: ' + (response?.data.message || '未知错误'));
            }
          } catch (error) {
            console.error('添加问题失败 (Catch):', error);
            ElMessage.error('添加问题时发生网络错误或未知异常');
          }
        } else {
          ElMessage.warning('请输入问题描述');
          return false; // 阻止提交
        }
      });
    },
  },
};
</script>

<style scoped>
/* --- 通用页面样式 --- */
.page-container {
  position: relative;
  display: flex;
  max-width: 1600px; argin: 0 auto
  margin: 0 auto;
  padding: 20px;
  overflow-x: hidden; /* 防止主容器水平滚动 */
}

.content-wrapper {
  width: 100%; /* 初始占满宽度 */
  max-width: 100%; /* 覆盖固定的最大宽度 */
  padding-right: 0; 时应用 margin-le */
  transition: margin-left 0.3s cu
  transition: margin-left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* --- 面包屑 --- */
.breadcrumb {
  margin-bottom: 20px; /* 更多间距 */
}

/* --- 页面头部 --- */
.header {
  display: flex;
  flex-wrap: wrap; space-betw
  gap: 15px; tems: center;

  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}
.header .controls {
  /* 复用 Project.vue 的 controls 样式 */
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}
.header h2 {
  margin: 0;
  color: #303133;
  font-size: 24px; -space: no
  white-space: nowrap; or: #303133;
}
.right-controls {
  display: flex;
  flex-wrap: wrap; er;
  gap: 1
  gap: 10px; /
  flex-w
  align-items: center;
}
.status-buttons .el-button {
  padding: 8px 12px; /* 调整按钮内边距 */
}
.mode-toggle {
  padding: 8px 12px;
}

/* --- 筛选区域 --- */
.filter-section {
  margin-bottom: 25px;
  padding: 15px 20px;
  background: #f0f2f5; adius: 6px;

  border-radius: 6px;
}

.filter-form {
  display: flex;
  flex-wrap: wrap; er;
  flex
  gap: 15px 20px; 行 */
  gap: 1
  align-items: center;
}

.filter-item {
  margin-bottom: 0; /
  flex: 0 1 auto;
  margin-bottom: 0; ex: 0 1 auto;
}
/* 筛选按钮组推到右侧 */
.filter-buttons {
  /* margin-left: auto; 当空间足够时推到最右 */
  flex-shrink: 0; /* 防止按钮组被压缩 */
}

/* --- 卡片模式 --- */
.task-cards-wrapper {
  display: flex;
  flex-direction: column; /* 垂直排列卡片和分页 */
  gap: 25px; /* 间距 */
}
.task-cards {
  display: grid; /* 使用 Grid 布局 */
  /* 自动适应列数：最小宽度 360px，最大占满剩余空间 */
  grid-template-columns: repeat(auto-fit, minmax(380px, 400px));
  gap: 25px; /* 卡片间距 */
}

.task-card {
  position: relative;
  display: flex;  8px; /* 边角柔和 */
  bord
  flex-direction: column; 柔和的边框 */
  pad
  padding: 20px;
  overflow: hidden;
  background: #ffffff;
  border: 1px solid #e5e7eb; w: hidden;

  border-radius: 8px;
  display: f
  cursor: pointer;
  transition: all 0.2s ease-in-out; * 垂直堆叠内部元素 */
  /* 宽度由 Grid 控制，移除固定宽度 */
}

.task-card:hover {
  border-color: #dcdfe6; 4px); /* 悬浮效
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08); 0.08); /* 更柔
  transform: translateY(-4px);  /* 更低调的高亮 */
}

/* 保留装饰性顶部线条 */
.task-card::before {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: linear-gradient(90deg, #409eff 0%, #67c23a 100%);
  opacity: 0.7;
  content: '';
}

.card-header {
  display: flex;
  flex-wrap: nowrap; ace-between;

  align-items: flex-start; 顶部对齐 */

  justify-content: space-between;
  margin-bottom: 12px;
}

.task-title {
  flex-grow: 1; ont-size: 18px; /
  margin: 0;
  padding-right: 10px; or: #303133;

  overflow: hidden;
  color: #303133;
  font-weight: 600;
  font-size: 18px; t-overflow:
  line-height: 1.4;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.card-status-tag {
  flex-shrink: 0; /* 防止标签被压缩 */
  margin-left: 10px; /* 与标题的间距 */
  /* 移除下边距，由 header 控制 */
}

.card-content {
  /* el-descriptions */
  flex-grow: 1; x; /* 描述内容字号减小 *
  margin-bottom: 15px;  /* 与操作按钮的间距 *
  font-size: 13px;  允许描述区域填充空间 */
}
/* 调整 el-descriptions 内部样式 */
.card-content :deep(.el-descriptions__label) {
  width: 70px; /* 标签宽度减小 */
  color: #606266;
  font-size: 13px;
}
.card-content :deep(.el-descriptions__content) {
  font-size: 13px;
}
.card-content :deep(.el-descriptions__cell) {
  padding: 6px 8px; /* 单元格内边距减小 */
}
.description-item {
  position: relative;
  margin-bottom: 10px;
}
.description-item .el-form-item__content {
  display: flex;
  align-items: center;
  margin-left: 0 !important;
}
.remove-desc-btn {
  width: 16px;
  height: 16px;
  margin-left: 8px;
  padding: 0;
  font-size: 16px;
}

.edit-form .el-button--link {
  /* "增加描述项" 按钮 */
  margin-top: -10px;
  margin-left: 100px; /* 与标签对齐 */
}

/* --- 表格状态列 --- */
.task-table .el-tag {
  /* 确保标签有足够空间 */
  margin-right: 5px; /* 如果有多个标签 */
}

.card-actions {
  display: flex;
  flex-wrap: wrap; 减小 */
  marg
  gap: 8px;  /* 将按钮推到底部
  margin-top: auto; x; /* 与上方内容的间
  padding-top: 10px;  solid #f0f2f5
  border-top: 1px solid #f0f2f5; 允许按钮换行 */
}

.card-actions .el-button {
  padding: 4px 8px;
  font-size:
  color: #606266;
  font-size: 13px; * 按钮内边距 */
  transition: color 0.2s ease;
}
.card-actions .el-button:hover {
  color: #409eff;
}
/* 删除按钮推到最右侧 */
.card-actions .delete-btn {
  margin-left: auto;
}
.card-actions .delete-btn:hover {
  color: #f56c6c;
}
/* 默认隐藏删除按钮 */
/* .card-actions .delete-btn {
   opacity: 0;
   transform: scale(0.8);
   transition: opacity 0.2s ease, transform 0.2s ease;
} */
/* 卡片悬停时显示删除按钮 */
/* .task-card:hover .delete-btn {
    opacity: 1;
    transform: scale(1);
} */

/* --- 表格模式 --- */
.task-table-wrapper {
  width: 100%;
  overflow-x: auto; /* 在包裹容器上启用水平滚动 */
}
.task-table {
  width: 100%; /* 表格宽度占满包裹容器 */
  /* 最小宽度确保表格不会被过度压缩，出现水平滚动条 */
  min-width: 1000px; /* 根据实际列数调整 */
}
/* 表格单元格内按钮的样式 */
.task-table :deep(.el-table__cell .cell .el-button) {
  margin: 0 4px; /* 按钮左右间距 */
  padding: 3px 6px; /* 内边距 */
  font-size: 12px; /* 字号 */
}

/* --- 分页 --- */
.pagination {
  display: flex;
  justify-content: flex-end; -content:
  margin-top: 25px;
  padding: 0 5px; /* 轻微内边距 */
}

/* --- 侧边栏 (卡片模式变更记录) --- */
.sidebar {
  position: fixed; 固定宽度 */

  top: 0;
  left: 0;
  z-index: 1050; und: #fff;
  display: flex; : #606266;
  trans
  flex-direction: column;  初始隐藏在左侧 */
  transition: t
  width: 400px; ic-bezier(
  height: 100vh; * 平滑过渡 */

  color: #606266;
  background: #fff; 的边框 */
  p
  border-right: 1px solid #e5e7eb;  left: 0;

  transform: translateX(-100%); lay: flex; /*
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); Content */
}
.sidebar.visible {
  box-shadow: 4px 0 12px rgba(0, 0, 0, 0.08); hadow: 4px 0
  transform: translateX(0); 打开时显示阴影 */
}
.sidebar-header {
  display: flex;
  flex-shrink: 0;  space-betwee
  align-items: center;
  justify-content: space-between;
  padding: 15px 20px;
  background: #f9fafb; fb; /* 浅色头部背
  border-bottom: 1px solid #e5e7eb;
}
.sidebar-header h3 {
  max-width: calc(100% - 40px); /* 标题字号 */
  font-w
  margin: 0;
  overflow: hidden;
  font-weight: 600;
  font-size: 16px; rap;
  max
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* 侧边栏关闭按钮 */

.sidebar-content {
  flex-grow: 1; 
  flex-grow: 1;
  padding: 20px;
  overflow-y: auto; /* 内容溢出时允许滚动 */
}
.sidebar-filter-form .el-form-item {
  margin-bottom: 15px; /* 表单项间距 */
}
.sidebar-button-group {
  margin-top: 10px; /* 按钮组上方间距 */
}

/* --- 变更记录弹窗 (表格模式) --- */
/* 调整弹窗 body 内边距 */
.change-log-dialog :deep(.el-dialog__body) {
  padding: 15px 25px 25px 25px;
}
/* 弹窗内筛选表单项间距 */
.dialog-filter-form .el-form-item {
  margin-bottom: 15px;
}
/* 弹窗内按钮组容器样式 */
.dialog-button-group {
  margin-top: 5px;  /* 移除容器下边距 */

  margin-bottom: 0;  与日期选择器的间距 */
}
/* 弹窗内时间线列表样式 */
.dialog-changes-list {
  max-height: 55vh; /* 列表上方间距 */

  margin-top: 20px; 最大高度，允许滚动 */
  padding-right: 10px;
   padding-right
  overflow-y: auto;
}

/* --- 时间线样式 (侧边栏和弹窗共用) --- */
.timeline {
  position: relative;
  margin: 0;
  padding: 0;
  list-style: none;
}
.timeline::before {
  /* 垂直线 */
  position: absolute;
  top: 5px; ute; top: 5p
  left: 4px;  */ left:
  width: 2px;
  height: calc(100% - 5px);
  background: #e5e7eb; ound: #e5e7eb;
  content: '';
}
.timeline-item {
  /* 单项 */
  position: relative;
  margin-bottom: 18px; * 左侧留空给圆点
  padding-left: 25px; px; /* 项间距 */
}
.timeline-item::before {
  /* 圆点 */
  position: absolute;
  top: 5px; ute; left:
  left: 0px; 置 */ top:
  width: 10px;
  height: 10px;
  background: #409eff;
  border: 2px solid #fff; dius: 50%; bor
  border-radius: 50%;
  box-shadow: 0 0 0 1px #409eff; 0 1px #409
  content: '';
}
.timeline-content {
  /* 内容块 */
  padding: 12px 15px;
  background: #f9fafb; 12px 15px;
  border: 1px solid #f0f2f5;  1px solid
  border-radius: 6px;
}
.change-description {
  /* 变更描述文本 */
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 0;
  color: #303133;
  font-size: 13px;
  line-height: 1.5;
  word-break: break-word;
}
.change-description .el-icon {
  /* 图标 */
  margin-top: 2px; ; margin-top
  color: #909399;
}
.change-details {
  /* 具体变更列表 */
  margin: 6px 0 0 0; /* 调整上边距 */
  padding-left: 20px;
  color: #555;
  font-size: 13px;
  list-style-type: disc;
}
.change-details li {
  /* 具体变更项 */
  margin-bottom: 4px;
}
.no-selection {
  /* 无记录提示 */
  padding: 30px 15px;
  color: #909399;
  font-size: 14px;
  text-align: center;
}

/* --- 任务详情弹窗 --- */
.details-dialog :deep(.el-dialog__body) {
  padding: 15px 25px 25px 25px; /* 调整内边距 */
}
.details-content {
  max-height: 65vh; /* 允许更高的高度 */
  padding-right: 10px; adding-righ
  overflow-y: auto;
}
.detail-item {
  display: flex;
  align-items: flex-start;
  margin-bottom: 12px; /* 减小间距 */
  font-size: 14px;
}
.detail-item.long-text {
  flex-direction: column;
  align-items: stretch;
}
.detail-item .label {
  flex-shrink: 0;
  min-width: 90px;
  padding-right: 10px;
  color: #555;
  font-weight: 500;
}
.detail-item .value {
  flex-grow: 1;
  color: #303133;
  word-break: break-word;
}
/* 详情中的状态标签 */
.detail-item .status-tag {
  vertical-align: middle; /* 使标签与文字垂直对齐 */
}
/* 长文本的值区域样式 */
.detail-item.long-text .value {
  max-height: 180px;
  margin-top: 4px;
  padding: 10px;
  overflow-y: auto;
  color: #444;
  line-height: 1.6;
  white-space: pre-wrap;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 4px;
}

/* --- 编辑/新增/问题 弹窗 --- */
.edit-dialog :deep(.el-dialog__body),
.problem-dialog :deep(.el-dialog__body) {
  padding: 25px 25px 10px 25px; /* 调整内边距，底部留空少 */
}
/* 表单项间距 */
.edit-form .el-form-item {
  margin-bottom: 18px;
}

/* 小任务容器样式 */
.subtask-container {
  position: relative;
  display: flex;
  align-items: flex-start;
  width: 100%;
}

.subtask-checkbox {
  margin-top: 8px;
  margin-right: 10px;
}

.remove-desc-btn {
  top: 10px;
  right: 0;
  min-height: auto;
  padding: 6px;
}

/* 详情页小任务列表样式 */
.subtasks-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.subtask-item {
  padding: 4px 0;
}

.subtask-content {
  display: flex;
  gap: 8px;
  align-items: center;
}

.completed-subtask {
  color: #909399;
  text-decoration: line-through;
}

/* --- 删除确认 Popover/MessageBox --- */

/* MessageBox 确认框样式 */
.delete-message-box {
  border-radius: 6px;
}
.delete-message-box .el-message-box__header {
  padding: 12px 15px;
  border-bottom: 1px solid #e5e7eb;
}
.delete-message-box .el-message-box__title {
  color: #303133;
  font-weight: 600;
  font-size: 16px;
}
.delete-message-box .el-message-box__content {
  padding: 20px 15px;
  color: #606266;
  font-size: 14px;
}
/* MessageBox 确认按钮红色 */
.delete-message-box .el-button--primary {
  background-color: #f56c6c;
  border-color: #f56c6c;
}
.delete-message-box .el-button--primary:hover {
  background-color: #f89898;
  border-color: #f89898;
}

/* --- 通用响应式调整 --- */
/* 适配平板等中等屏幕 */
@media (max-width: 1024px) {
  .task-cards {
    /* 平板上调整列宽和间距 */
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 20px;
  }
  .task-table {
    min-width: 800px; /* 减小表格最小宽度 */
  }
}

@media (min-width: 769px) {
  /* 只在大屏幕应用 */
  .content-wrapper.sidebar-open {
    margin-left: 400px; /* 等于侧边栏的宽度 */
    /* 可以 transition，但你已有 transitionStyle */
    /* transition: margin-lef
    width: calc(100% - 400px); 1); */
     width:
    margin-left: 400px; ：如果需要动态计算宽度 */
  }
}

/* 适配手机等小屏幕 */
@media (max-width: 768px) {
  .page-container {
    padding: 15px; /* 减小页面内边距 */
  }
  .content-wrapper.sidebar-open {
    margin-left: 0; /* 小屏幕时侧边栏是底部抽屉，不推内容 */
    /* margin-bottom: 60%;  */ /* 如果抽屉高度固定，可能需要这个，但 fixed 定位通常不需要 */
  }

  .header {
    flex-direction: column; /* 垂直排列 */
    align-items: flex-start; /* 左对齐 */
    margin-bottom: 15px;
  }
  .header h2 {
    margin-bottom: 10px; 小标题字号 */

    font-size: 20px; * 标题和控件间距 */
  }
  .right-controls {
    width: 100%;
    /* justify-content: space-between
    gap: 8px; */
    gap:
    width: 100%;
  }
  .filter-section {
    padding: 10px 15px;
  }
  .filter-form {
    gap: 10px; /* 减小筛选条件间距 */
  }
  .filter-item {
    /* 大致实现两列布局，允许增长 */
    flex-basis: calc(50% - 10px);
    flex-grow: 1;
  }
  /* 让输入框和日期选择器宽度占满 */
  .filter-item .el-input,
  .filter-item .el-date-picker,
  .filter-item .el-select {
    /* 如果有下拉选择 */
    width: 100% !important;
  }
  /* 筛选按钮单独占一行，并靠右 */
  .filter-buttons {
    display: flex; %; /* 占满整行 */

    flex-basis: 100%; 自动左边距 */

    justify-content: flex-end;  按钮靠右 */

    margin-left: 0; 启用 flex 布局 */
  }

  .task-cards {
    /* 手机上变为单列 */
    grid-template-columns: 1fr;
    gap: 15px; /* 减小卡片间距 */
  }

  /* --- 侧边栏变为底部抽屉 --- */
  .sidebar {
    top: auto; ; /* 宽度占满 */
    bottom: 0; ; /* 高度可调，例
    z-index: 1100;  auto; /* 取消顶部
    width: 100%; 0; /* 定位到底
    height: 60%; : translateY(100%);
    border-top: 1px solid #e5e7eb; ne; /* 移除右边框
    border-right: none; olid #e5e7e
    box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.08); , 0, 0, 0.
    transform: translateY(100%);  /* 比一般弹窗层级高 */
  }
  .sidebar.visible {
    transform: translateY(0); /* 滑入屏幕 */
  }

  /* 弹窗宽度已由计算属性 dialogWidth 控制 */

  /* 手机上表格操作按钮可考虑只显示图标 (按需启用) */
  /* .task-table :deep(.el-table__cell .cell .el-button span:not(.el-icon)) {
        display: none;
   } */
  .task-table :deep(.el-table__cell .cell .el-button) {
    margin: 0 2px; /* 进一步减小按钮间距 */
  }

  .header .controls {
    gap: 8px;
    width: 100%;
  }
  .controls .status-filter-select {
    /* 筛选下拉框 */
    flex-grow: 1;
    min-width: 150px;
  }
  .controls .mode-toggle {
    /* 视图切换按钮 */
    margin-left: auto;
  }

  .edit-form .el-button--link {
    /* 调整 "增加描述项" 按钮位置 */
    margin-left: 0;
  }
  .description-item .el-input {
    /* width: calc(100% - 40px) !important; */ /* 按需调整 */
  }
}

.empty-state {
  /* 空状态提示样式 */
  grid-column: 1 / -1; ding: 40px 0;
     g
  width: 100%;
  padding: 40px 0;
}

/* ... 其他样式 ... */
.pretty-table .el-table__header th {
  color: #333;
  font-weight: 600;
  font-size: 15px;
  background: #f5f7fa;
  border-bottom: 2px solid #e4e7ed;
}
.pretty-table .el-table__row {
  font-size: 14px;
  transition: background 0.2s;
}
.pretty-table .el-table__row.current-row {
  background: #e6f7ff !important;
}
.pretty-table .el-table__body td {
  border-bottom: 1px solid #f0f0f0;
}
.pretty-table .action-col .el-button {
  margin: 0 2px;
}
.pretty-table .el-tag {
  padding: 2px 10px;
  font-size: 13px;
  border-radius: 6px;
}
.pretty-empty {
  margin-top: 40px;
  color: #aaa;
  font-size: 16px;
}

/* 卡片底部 */
.card-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed #f0f2f5;
}

.delete-btn {
  color: #f56c6c;
}
</style>
